from google.appengine.api import users, urlfetch
from plzkeepthat.common.util import get_notelist
from plzkeepthat.models.models import Note
from plzkeepthat.models.util import dbutils
from plzkeepthat.views.forms.forms import AddForm
import logging
import re
import random
from HTMLParser import HTMLParser
from google.appengine.ext import db

#===============================================================================
# Utils for parsing Notes
#===============================================================================

class NoteParser:
    """
    Creates a Note object including corresponding Tags and relations
    from a given form. 
    """
    def __init__(self, form, id = None):
        """ Initializes the object. """
        self.note = None
        self.tags = []
        self.__id = id
        self.__raw_message = form.clean_data['text']
        self.__raw_tags = form.clean_data['tags']
        self.__notelist = get_notelist(users.get_current_user())

    def parse(self):
        self.__parse_note_form()
        self.__get_tag_list()

    def __get_url(self):
        result = re.search(r'(((http://)|(www\.)|(ftp://)|(https://))[\S]+)', self.__raw_message)
        if result is not None:
            url = result.group()
            if url.startswith('www.'):
                url = 'http://' + url
            return url
        else:
            return None

    def __get_note_by_id(self):
        return dbutils.get_note_by_id(self.__id, self.__notelist)

    def __get_tag(self, tag):
        return dbutils.get_or_insert_tag_by_name(tag, self.__notelist)

    def __get_note_tag_list(self):
        return dbutils.get_tags_for_note(self.note)

    def __get_tag_list(self):
        logging.info("### raw tags %s " % self.__raw_tags)
        if self.__id:
            dbutils.delete_all_tags(self.note)
        for tagname in self.__raw_tags:
            if tagname is not None and tagname != "":
                tag = self.__get_tag(tagname)
                self.tags.append(tag)

    def __parse_note_form(self):
        url = self.__get_url()

        prefetchUrl = prefetch_picture_url(url)
        logging.debug(prefetchUrl)
        img = None
        try:
            if prefetchUrl is not None: img = db.Blob(prefetch_picture(url))
        except: pass
            
        if not self.__id:
            self.note = Note(text = self.__raw_message, url = url, noteList = self.__notelist, image = img)            
        else:
            note = self.__get_note_by_id()
            if note is None:
                logging.error("Could not fetch object")
            else:
                note.text = self.__raw_message
                note.url = url
                note.prefetchURL = prefetchUrl

            self.note = note

class PictureParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.picture_urls = []

    def handle_starttag(self, tag, attrs):
        if tag == 'img':
            for name, value in attrs:
                if name == 'src': self.picture_urls.append(value)

class ShareParser:
    def __init__(self, user, form, note):
        self.recipients = form.clean_data["to"]
        self.subject = form.clean_data["subject"]
        self.message = form.clean_data["message"]
        self.sender = user.email()
        self.note = note
    

def get_add_form(note):
    """ Creates an AddForm from the given Note object """
    l = []
    [l.append(t.text) for t in dbutils.get_tags_for_note(note)]
    tags_csl = ", ".join(l)
    logging.debug(tags_csl)
    return AddForm({"text" : note.text,
                    "tags" : tags_csl
                    })

def __prepare_url(url):
    if url is None: return ""
    cleaned_url = re.search(r'(((http://|https://)?)www\.\w*.\w*(/?)(\w*/)*(/?\w*.(jpg|jpeg))?)', url)
    if cleaned_url is not None:
        result = cleaned_url.group()
        logging.debug(result)
        if not result.endswith("/"): "/".join((result, ""))
        return result
    else: return ""

def __is_absolute_url(url):
    return url.startswith("http://") \
        or url.startswith("https://")
        
def fetch_image(image_url):
    result = urlfetch.fetch(image_url)
    if result.status_code == 200: return result.content
    else: return None

def prefetch_picture(url):
    return fetch_image(prefetch_picture_url(url))

def prefetch_picture_url(url):
    if url is None: return None
    try:
        result = urlfetch.fetch(url)
    except:
        return None

    if result.status_code == 200:
        parser = PictureParser()
        try:
            parser.feed(result.content)
        except: return None
        parser.close()
            
        length = len(parser.picture_urls)
        if length > 0:
            img_url = parser.picture_urls[random.randint(0, length - 1)]
            result = None
            if __is_absolute_url(img_url): result = img_url
            else: result = "".join([__prepare_url(url), img_url])
            return result
        else: return None
    else: return None
